package com.jtw.sys.task.systeminit;

import com.jtw.common.anno.RequestAnno.PermAnno;
import com.jtw.common.bean.enums.PermGroup;
import com.jtw.common.util.RandomUtil;
import com.jtw.common.util.SpringUtil;
import com.jtw.conf.shiro.util.ShiroUtil;
import com.jtw.sys.constants.Constant;
import com.jtw.sys.mapper.member.MemberAssetMapper;
import com.jtw.sys.mapper.menu.SysMenuMapper;
import com.jtw.sys.mapper.perm.SysPermGroupMapper;
import com.jtw.sys.mapper.perm.SysPermMapper;
import com.jtw.sys.mapper.user.SysRoleMapper;
import com.jtw.sys.mapper.user.SysUserInfoMapper;
import com.jtw.sys.mapper.user.SysUserMapper;
import com.jtw.sys.model.member.TSysMemberAsset;
import com.jtw.sys.model.perm.TSysPerm;
import com.jtw.sys.model.perm.TSysPermGroup;
import com.jtw.sys.model.task.TSysTask;
import com.jtw.sys.model.user.TSysRole;
import com.jtw.sys.model.user.TSysUser;
import com.jtw.sys.model.user.TSysUserInfo;
import com.jtw.sys.service.perm.AuthService;
import com.jtw.sys.service.system.ConfigServiceImpl;
import com.jtw.sys.service.task.SysTaskServiceImpl;
import com.jtw.sys.util.TaskUtil;
import com.jtw.sys.vo.menu.SysMenuRoleMarkModifyReq;
import com.jtw.sys.vo.perm.SysRolePermAddVo;
import com.jtw.sys.vo.role.SysRoleUpdateVo;
import com.jtw.sys.vo.task.TaskModelVo;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.reflections.Reflections;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.lang.reflect.Method;
import java.util.*;

/**
 * 系统初始化时候的任务
 *
 * @author cjsky666
 * @date 2018-8-21 14:52
 */
@Component
@Slf4j
public class OnStartTask implements CommandLineRunner {

    private static Map<String,Integer> gameMap = new HashMap<>();//系统对应的定时任务、参数id

    @Autowired
    private ShiroFilterFactoryBean shiroFilterFactoryBean;
    @Autowired
    private  AuthService authService;
    @Autowired
    private  SysRoleMapper sysRoleMapper;
    @Autowired
    private  SysUserInfoMapper sysUserInfoMapper;
    @Autowired
    private  SysUserMapper sysUserMapper;
    @Autowired
    private  SysPermMapper sysPermMapper;
    @Autowired
    private  SysPermGroupMapper sysPermGroupMapper;
    @Autowired
    private SysMenuMapper sysMenuMapper;
    @Autowired
    private ConfigServiceImpl configServiceImpl;
    @Autowired
    private MemberAssetMapper memberAssetMapper;

    @Override
    @Transactional
    public void run(String... args) throws Exception {
        log.info("系统初始化任务--->开始");
        initOsEnvironment();//打印环境变量信息
        initSystemProperties();//打印系统变量信息
        initSystemPermGroupTask();//系统权限组表
        initSystemPermTask();//系统权限表
        initAdminAccountTask();//超级管理账号
        initAdminRolePermTask();//超级管理员角色权限
        initAdminAccountRoleTask();//超级管理账号的超级管理员角色
        initAdminRoleMenusTask();//超级管理员角色的菜单
        initAdminLoginPerm();//超级管理员后台的登陆权限
        initMemberRoleAndPerm();//会员角色及角色权限
        initSysConfig();//初始化系统配置信息
        initTaskAndTaskGameConfig();//初始化系统定时任务调度
        //初始化重置shiro权限核心任务
        try {
            ShiroUtil.updateFilterChain(shiroFilterFactoryBean,authService);
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("系统初始化任务--->完毕");
    }



    private void initMemberRoleAndPerm() {
        log.info("初始化会员角色检测--->开始");
        TSysRole tSysRole = sysRoleMapper.selectByPrimaryKey(Constant.ROLE_ID_MEMBER);
        if (tSysRole==null){
            tSysRole = new TSysRole();
            tSysRole.setId(Constant.ROLE_ID_MEMBER);
            tSysRole.setName("会员");
            tSysRole.setDesc("系统会员角色(请勿删除)");
            tSysRole.setCreateTime(new Date());
            tSysRole.setUpdateTime(new Date());
            tSysRole.setOperator("admin");
            tSysRole.setOperatorIp("127.0.0.1");
            sysRoleMapper.insert(tSysRole);
        }
        log.info("初始化会员角色检测--->完毕");
    }

    private void initSysConfig() {
        log.info("初始化系统配置表--->开始");
        Constant.sysConfMap = configServiceImpl.getAllConfig();
        log.info("初始化系统配置表--->完毕");
    }

    private void initGameConfig(List<TSysTask> tSysTasks) {
        log.info("初始化系统定时任务--->开始");
        for(TSysTask s:tSysTasks){
            gameMap.put(s.getParam(),s.getGameId());
        }
        log.info("初始化系统定时任务--->开始");
    }

    private void initOsEnvironment(){
        log.info("打印--环境变量信息--->开始");
        Map map = System.getenv();
        Iterator it = map.entrySet().iterator();
        while(it.hasNext())
        {
            Map.Entry entry = (Map.Entry)it.next();
            log.info("当前环境变量"+entry.getKey()+"的值是："+entry.getValue());
        }
        log.info("打印--环境变量信息--->结束");
    }

    private void initSystemProperties(){
        log.info("打印--系统变量信息--->开始");
        Properties properties = System.getProperties();
        Iterator it =  properties.entrySet().iterator();
        while(it.hasNext())
        {
            Map.Entry entry = (Map.Entry)it.next();
            log.info("当前系统变量"+entry.getKey()+"的值是："+entry.getValue());
        }
        log.info("打印--系统变量信息--->结束");
    }

    private  void initAdminAccountRoleTask() {
        log.info("初始化超级管理员账号--角色检测--->开始");
        if(!sysRoleMapper.isSysRoleExisting(1)){
            TSysRole sysRole = new TSysRole();
            sysRole.setId(1);
            sysRole.setName("超级管理员");
            sysRole.setDesc("系统最高级别角色(请勿删除)");
            sysRole.setOperator("admin");
            sysRole.setOperatorIp("0.0.0.0");
            sysRole.setCreateTime(new Date());
            sysRole.setUpdateTime(new Date());
            sysRoleMapper.insert(sysRole);
        }

        List<SysRoleUpdateVo> roles = sysUserMapper.getUserRolesByUserId(1L);
        boolean onAdmin  = true;
        for(int i = 0;i<roles.size();i++){
            if(roles.get(i).getId()==1){
                onAdmin=false;
            }
        }
        if(onAdmin){
            log.info("检测到超级管理员账号的角色未拥有相关权限-重新恢复-->开始");
            sysUserMapper.insertUserRolesByUserId(Constant.USER_ID_SUPER_ADMIN,new Integer[]{1},"admin","0.0.0.0");
            log.info("检测到超级管理员账号的角色未拥有相关权限-重新恢复-->完毕");
        }
        log.info("初始化超级管理员账号--角色检测--->完毕");
    }

    private void initAdminRolePermTask() {
        log.info("初始化超级管理员角色权限检测--->开始");
        List<TSysPerm> sysPermList = sysPermMapper.selectAll();
        List<SysRolePermAddVo> sysRolePermAddVos = sysPermMapper.getAllRolePermsByRoleId(Constant.ROLE_ID_SUPER_ADMIN);
        List<Integer> ids = new ArrayList<Integer>();
        for(TSysPerm s : sysPermList){
            if(s.getOpen()){
                continue;
            }
            ids.add(s.getId());
        }

        if(ids.size()!=sysRolePermAddVos.size()){
            sysRoleMapper.deleteRoleWithPerm(Constant.ROLE_ID_SUPER_ADMIN);
            sysPermMapper.modifyRolePerms(Constant.ROLE_ID_SUPER_ADMIN, (Integer[]) ids.toArray(new Integer[0]));
        }
        log.info("初始化超级管理员角色权限检测--->完毕");
    }

    private void initAdminLoginPerm(){
        if(!sysUserMapper.isAdmin(Constant.USER_ID_SUPER_ADMIN)){
            log.info("检测到超级管理员账号未拥有后台登陆权限--正在恢复--开始");
            sysUserMapper.addAdminLoginPerm(Constant.USER_ID_SUPER_ADMIN);
            log.info("检测到超级管理员账号未拥有后台登陆权限--正在恢复--成功");
        }
    }

    public void initSystemPermGroupTask() {
        log.info("初始化系统权限组检测--->开始");
        List<TSysPermGroup> list = sysPermGroupMapper.selectAll();
        List<TSysPermGroup> t_list = new ArrayList<TSysPermGroup>();
        for (PermGroup permGroup : PermGroup.values()) {
            boolean flag = false;
            for (TSysPermGroup sysPermGroup : list) {
                if (sysPermGroup.getGroup().equals(permGroup.getGroup())) {
                    flag  = true;
                    continue;
                }
            }
            if(!flag){
                TSysPermGroup tSysPermGroup = new TSysPermGroup();
                tSysPermGroup.setDesc(permGroup.getDesc());
                tSysPermGroup.setGroup(permGroup.getGroup());
                t_list.add(tSysPermGroup);
            }
        }
        if(t_list.size()>0){
            log.info(t_list.toString());
            sysPermGroupMapper.insertList(t_list);
            log.info(t_list.toString());
        }
        log.info("初始化系统权限组检测--->完毕");
    }


    public void initSystemPermTask() {
        log.info("初始化系统权限检测--->开始");
        List<String> permList = sysPermMapper.getAllPermUrl();
        Reflections reflections = new Reflections("com.jtw.sys.controller");
        List<TSysPerm> tSysPermList = new ArrayList<TSysPerm>();
        Set<Class<?>> classesList = reflections.getTypesAnnotatedWith(RequestMapping.class);
        for (Class c : classesList) {
            if (c.getName().startsWith("com.jtw.sys.controller")) {
                Method[] methods = c.getMethods();
                for (Method m : methods) {
                    boolean isExist = m.isAnnotationPresent(PermAnno.class);
                    if (!isExist) {
                        continue;
                    }
                    TSysPerm sysPerm = new TSysPerm();
                    RequestMapping requestMapping = null;
                    requestMapping = (RequestMapping) c.getAnnotation(RequestMapping.class);
                    sysPerm.setClassName(c.getName());
                    sysPerm.setMethodName(m.getName());

                    GetMapping getMapping = m.getAnnotation(GetMapping.class);
                    if (getMapping != null) {
                        sysPerm.setHttpMethod(RequestMethod.GET.toString());
                        sysPerm.setUrl(requestMapping.value()[0] + getMapping.value()[0]);
                    } else {
                        PostMapping postMapping = m.getAnnotation(PostMapping.class);
                        sysPerm.setHttpMethod(RequestMethod.POST.toString());
                        sysPerm.setUrl(requestMapping.value()[0] + postMapping.value()[0]);
                    }
                    PermAnno permAnno = m.getAnnotation(PermAnno.class);
                    sysPerm.setOpen(permAnno.open());
                    sysPerm.setState(permAnno.state());
                    sysPerm.setGroup(permAnno.group());
                    sysPerm.setSort(permAnno.sort());
                    sysPerm.setType(permAnno.type());
                    ApiOperation apiOperation = m.getAnnotation(ApiOperation.class);
                    sysPerm.setName(apiOperation.value());
                    sysPerm.setDesc(apiOperation.notes());
                    log.info(sysPerm.toString());
                    if (!permList.contains(sysPerm.getUrl())) {
                        sysPerm.setOperator("admin");
                        sysPerm.setOperatorIp("0.0.0.0");
                        sysPerm.setCreateTime(new Date());
                        sysPerm.setUpdateTime(new Date());
                        tSysPermList.add(sysPerm);
                    }
                }
            }
        }
        if(tSysPermList.size()>0){
            sysPermMapper.insertList(tSysPermList);
        }
        log.info("初始化系统权限检测--->完毕");
    }

    public void initAdminRoleMenusTask(){
        log.info("初始化超级管理员后台管理菜单--->开始");
        Integer [] menus =  sysMenuMapper.getAllMenusByRoleIdNotHave(1);
        if(menus.length>0){
            SysMenuRoleMarkModifyReq sysMenuRoleMarkModifyReq = new SysMenuRoleMarkModifyReq();
            sysMenuRoleMarkModifyReq.setRoleId(1);
            sysMenuRoleMarkModifyReq.setMenus(menus);
            sysMenuMapper.batchSaveRoleMenusByRoleId(sysMenuRoleMarkModifyReq);
        }
        log.info("初始化超级管理员后台管理菜单--->完毕");
    }

    public void initAdminAccountTask(){
        log.info("初始化超级管理员账号检测--->开始");
        TSysUser admin =  sysUserMapper.selectByPrimaryKey(Constant.ROLE_ID_SUPER_ADMIN);
        Date date = new Date();
        if(admin==null){
            admin = new TSysUser();
            admin.setId(Constant.USER_ID_SUPER_ADMIN);
            admin.setSalt("83c9a13a35e8b7024f4e7277c4f61e30");
            admin.setPassword("f2a0f081b46af688e7c8c795cc007450");//123456
            admin.setUserName("admin");
            admin.setOperator("admin");
            admin.setOperatorIp("0.0.0.0");
            admin.setState(0);
            admin.setCreateTime(date);
            admin.setUpdateTime(date);
            sysUserMapper.insert(admin);
        }
        TSysUserInfo tSysUserInfo = sysUserInfoMapper.selectByPrimaryKey(admin.getId());
        if(tSysUserInfo==null){
            tSysUserInfo = new TSysUserInfo();
            tSysUserInfo.setId(admin.getId());
            tSysUserInfo.setSex(3);
            tSysUserInfo.setNickName("admin");
            tSysUserInfo.setOperator("admin");
            tSysUserInfo.setOperatorIp("0.0.0.0");
            tSysUserInfo.setCreateTime(date);
            tSysUserInfo.setUpdateTime(date);
            sysUserInfoMapper.insert(tSysUserInfo);
        }
        TSysMemberAsset memberAsset = memberAssetMapper.selectByPrimaryKey(admin.getId());
        if(memberAsset==null){
            memberAsset = new TSysMemberAsset();
            memberAsset.setId(admin.getId());
            memberAssetMapper.insertSelective(memberAsset);
        }
        log.info("初始化超级管理员账号检测--->完毕");
    }

    /**
     * 初始化启动定时任务
     */
    public void initTaskAndTaskGameConfig(){


        // 这里从数据库中获取任务信息数据
        SysTaskServiceImpl sysTaskService = (SysTaskServiceImpl)SpringUtil.getBean(SysTaskServiceImpl.class);

        List<TSysTask> list = sysTaskService.getAll();
        log.info("获取所有计划任务--->成功");

        initGameConfig(list);

        log.info("初始化系统定时任务--->开始");
        for(TSysTask s:list){
            if(s.getTaskState()){
                log.info("开始设置计划任务--->"+s.getName(),"任务包名为"+s.getBeanClass(),"任务方法名为"+s.getMethodName());
                TaskModelVo taskModelVo = new TaskModelVo();
                BeanUtils.copyProperties(s, taskModelVo);
                TaskUtil.addTask(taskModelVo);
            }
        }
        log.info("初始化系统定时任务--->完毕");
    }
}
